package com.zygh.lz.securitys;

import com.zygh.lz.util.CommonUtil;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * security自带登录传参格式改成json
 * Spring Security-6：登录使用 body JSON 传参
 *
 * Spring Security默认登录方式入参格式为key-value形式，需继承UsernamePasswordAuthenticationFilter类
 * 重写attemptAuthentication 方法，手动修改入参格式为json
 *
 * ------------------------------------------------------------------------------------------------
 * UsernamePasswordAuthenticationFilter过滤器用于处理基于表单方式的登录验证，
 * 该过滤器默认只有当请求方法为post、请求页面为/login时过滤器才生效，
 * 如果想修改默认拦截url，只需在刚才介绍的Spring Security配置类WebSecurityConfig中
 * 配置该过滤器的拦截url：.loginProcessingUrl("url")即可;
 */
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private static final String APPLICATION_JSON_UTF8_VALUE_WITH_SPACE = "application/json; charset=UTF-8";
    private static final String USERNAME = "username";
    private static final String PASSWORD = "password";


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {



        // 通过 ContentType 判断是否是 JSON 登录
        String contentType = request.getContentType();
        if (MediaType.APPLICATION_JSON_UTF8_VALUE.equalsIgnoreCase(contentType) ||
                APPLICATION_JSON_UTF8_VALUE_WITH_SPACE.equalsIgnoreCase(contentType) ||
                MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(contentType)) {
            // 获取 body 参数 Map
            Map<String, Object> obj = CommonUtil.getBodyParametersFromRequest(request);
            // 使用用户名密码构建 Token
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                    obj.get(USERNAME), obj.get(PASSWORD));
            setDetails(request, token);

            return this.getAuthenticationManager().authenticate(token);
        } else {
            return super.attemptAuthentication(request, response);
        }
    }
}


